# this model expects a certain database layout and its based on the name/login pattern. 
class User < ActiveRecord::Base
  include ApplicationHelper
  
  has_many :tasks
  has_many :notes
  has_and_belongs_to_many :projects
  
  def self.authenticate(login, pass)
    find(:first, :conditions=>["login=? AND password=?", login,  ApplicationHelper.sha1(pass)])
  end  
  
  def self.find_with_cookie(value)
    User.find(:all).each { |u|
      return u if value ==  ApplicationHelper.sha1(u.login+u.password)
      }
    return nil  
  end
  
  def accept_invitation(inv_arr) # TODO: test multiple invitations
    inv_arr.each { |i|
      p = Project.find(i.project_id)
      projects << p if not projects.member?(p)
      i.destroy
    }
  end
  
  def decline_invitation(inv_arr) # TODO: test multiple invitations
    inv_arr.each { |i|
      i.destroy
    }
  end

  def late_tasks
    # TODO replace by Task.find (?)
    tasks.select{|t| t.done==0 and t.duedate and t.duedate <= Date.today}
  end
  
  def active_projects
    projects.select{|p| p.active==1}.sort_by {|p| [p.name.upcase]}
  end
  
  def active_projects_ids
    projects.select{|p| p.active==1}.collect{|p| p.id}
  end
  
  
  def self.select_tasks(user, project_id, resp_id, tags='',state='0')
    cond = "done='0'"
    user_projects = user.active_projects_ids.join(',')
    if user_projects != ''
      if project_id != 0
        cond += " and project_id='#{project_id}'"
      else
        cond += " and project_id in (#{user_projects})"
      end
      cond += " and user_id='#{resp_id}'" if resp_id != 0
    else
      cond += " and user_id='#{user.id}'"
    end
    cond += " and state='#{state}'"  if state != "0"
    if tags != ''
      # tag display and normal display is different: task_id is not filtered meaning that tree structured is not respected
      tasks = Task.find_tagged_with(tags, {:conditions=>cond, :include=>["user","tags"], :order=>'done, state, `order`'})
    else
      tasks = Task.find(:all, :conditions=>cond, :include=>["user","tags"], :order=>"done, state, `order`") #  + " and task_id=#{sel_task}"
    end
    #puts cond
    # gives only the tags of the current displayed tasks
    tags = tasks.inject([]) {|tags,t| tags += t.tags}.uniq.sort_by{|t| t.name.downcase}
    [tasks,tags,project_id,resp_id,state]
  end  
  
  protected

  before_create :crypt_password
  before_update :crypt_password_on_update
  
  def crypt_password
    #puts "Crypting"
    write_attribute("password",  ApplicationHelper.sha1(password))
  end
  
  validates_length_of :name, :within => 1..40
  validates_length_of :login, :within => 1..40
  validates_length_of :password, :within => 4..40
  validates_presence_of :login, :name
  validates_uniqueness_of :login, :case_sensitive => false
  validates_uniqueness_of :name, :case_sensitive => false # also the name as we assign users to projects by name
  validates_uniqueness_of :email, :case_sensitive => false, :if => Proc.new {|u| u.email and not u.email.empty?}
  validates_presence_of :password, :password_confirmation, :if => :validate_password_confirmation?
  validates_confirmation_of :password,:if => :validate_password_confirmation?
  
  def crypt_password_on_update
    crypt_password if validate_password_confirmation?
  end
  
  def validate_password_confirmation?
    (password and password_confirmation)
  end  
  
end

